import { message } from 'antd'
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
import axios, { AxiosError, AxiosHeaders } from 'axios'

// 初始化各项目特殊全局配置
let init = false
const initConfig: Partial<InitConfig> = {
  devlog: true,
  messageHandler(message, errCode) {
    alert(`message:${message},errCode:${errCode}`)
  }
}

const request = axios.create({
  headers: {
    platFormId: '4fc40d89c02a42489346e5d2eaac9444',
    Equipment: 'Web',
    ClientSystem: 'Web',
    ClientType: 'Web_backstage'
  }
})

const safeServerApiList = [
  '/safe/api/statistics/planStudySituationList2',
  '/safe/api/statistics/planStudySituationListByEnt',
  '/safe/api/statistics/getCycleStudyList',
  '/safe/api/statistics/getEntCycleStudyList',
  '/safe/api/statistics/assStudyPersonList2',
  '/safe/api/statistics/entStudyPersonList'
]

request.interceptors.response.use(
  (res: AxiosResponse<ResponseResult<unknown>, unknown>) => {
    const { data, request, config } = res
    // responseType === "blob":如果响应体是2进制格式,则手动处理一下
    // application/octet-stream':后端返回的是字节流（浏览器默认处理方式是下载）
    if (
      (config.responseType === 'blob' && data instanceof Blob) ||
      ((res.headers['content-type'] === 'application/octet-stream' ||
        res.headers['content-type'] === 'application/json') &&
        (config as any).getJsonFile)
    ) {
      res.data = {
        suc: true,
        data: data as unknown,
        errCode: '0',
        message: '请求成功',
        status: 0,
        go: undefined,
        total: undefined
      }
    }
    if (
      res.config.url &&
      safeServerApiList.includes(res.config.url) &&
      (res.data as any).code === 200
    ) {
      res.data.suc = true
    }
    if (res.data.suc) {
      return res
    } else {
      return Promise.reject(
        new AxiosError(res.data.message, res.data.errCode, config, request, res)
      )
    }
  }
)

type CreateUserMethodParams = Pick<
  AxiosRequestConfigExpand<unknown>,
  'headers' | 'method'
> & { getJsonFile?: boolean }
// 创建一个请求方法实例
function createUserMethod(mergeConfig: CreateUserMethodParams) {
  return function userMethod<R = undefined, D = unknown>(
    url: string,
    data?: D,
    config?: Omit<AxiosRequestConfigExpand<D>, 'data'>
  ) {
    return request<ResponseResult<R>, AxiosResponse<ResponseResult<R>, D>, D>({
      url: import.meta.env.VITE_BASE_API + url,
      data: mergeConfig.method === 'POST' ? data : undefined,
      params: mergeConfig.method === 'GET' ? data : undefined,
      ...mergeConfig,
      ...config,
      headers: Object.assign(
        new AxiosHeaders({
          ...initConfig.getHeaders?.()
        }),
        mergeConfig.headers,
        config?.headers
      )
    })
      .then((response) => {
        const logibeatResponseResult = response.data
        const config = Object.assign({}, initConfig, response.config)
        if (config.devlog) {
          // console.log(`请求接口:${config.url}`)
          // console.log(`请求响应:`, logibeatResponseResult)
        }

        if (logibeatResponseResult.suc) {
          config.showMsg && message.success(logibeatResponseResult.message)
          return logibeatResponseResult
        } else {
          return Promise.reject(
            new AxiosError(
              logibeatResponseResult.message,
              logibeatResponseResult.errCode,
              config,
              request,
              response
            )
          )
        }
      })
      .catch((err: AxiosError<ResponseResult<R>, D>) => {
        const logibeatResponseResult = (err.response?.data ?? {
          suc: false,
          message: '网络错误',
          errCode: 'Net_Work_Error',
          go: null,
          status: null,
          total: null
        }) as ResponseResult
        const config = Object.assign({}, initConfig, err.config)
        // 都需要处理这个异常
        if (config.messageHandler && !mergeConfig.getJsonFile) {
          config.messageHandler(
            logibeatResponseResult?.message ?? '网络异常',
            logibeatResponseResult?.errCode ?? 'Net_Work_Error'
          )
        }
        return Promise.reject(err)
      })
  }
}

const getData = createUserMethod({
  method: 'GET'
})

const getJson = createUserMethod({
  method: 'GET',
  getJsonFile: true
})

const postParam = createUserMethod({
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})

const postJson = createUserMethod({
  method: 'POST',
  headers: { 'Content-Type': 'application/json;charset=UTF-8' }
})

const postForm = createUserMethod({
  method: 'POST',
  headers: { 'Content-Type': 'multipart/form-data' }
})

/**
 * @desc 设置不同请求的头信息
 */
function defineAxiosExpandConfig(config: InitConfig) {
  if (init === false) {
    init = true
    Object.assign(initConfig, config)
  } else {
    console.warn('已经初始化过了无法二次初始化')
  }
}

export {
  defineAxiosExpandConfig,
  getData,
  getJson,
  postForm,
  postJson,
  postParam
}
export type { AxiosRequestConfigExpand, ResponseResult }

/**
 * @desc 物流云体系最常规通用请求响应体结构
 */
interface ResponseResult<T = undefined> {
  /**
   * @desc 请求是否成功
   */
  suc: boolean
  /**
   * @desc 服务器错误码，通知后端进行错误排查
   */
  errCode: string
  /**
   * @desc 请求结果信息
   */
  message: string
  /**
   * @desc 请求体真实数据,可能没有
   */
  data: T
  /**
   * @deprecated 没用
   */
  status: number
  /**
   * @deprecated 没啥用
   */
  go: unknown
  /**
   * @desc 如果请求的是列表则可能是总数
   */
  total: T extends Array<unknown> ? number : undefined
}

type InitConfig = {
  // 全局统一请求头扩充添加
  getHeaders?: () => Record<'baseuserid' | 'baseEntId' | 'ClientType', string>
  // 统一的错误信息处理方法
  messageHandler?:
    | ((message: string, errCode: string) => boolean | void)
    | false
  // 是否打印返回内容日志 @default=true
  devlog?: boolean
  showMsg?: boolean
  getJsonFile?: boolean
}

interface AxiosRequestConfigExpand<D>
  extends AxiosRequestConfig<D>,
    InitConfig {}
